﻿/**
 * @file std_queue.inl
 * Copyright (c) 2019 Gaaagaa. All rights reserved.
 * 
 * @author  : Gaaagaa
 * @date    : 2019-09-09
 * @version : 1.0.0.0
 * @brief   : 定义 FIFO队列容器 内部相关数据类型、常量、宏 等。
 */

/**
 * The MIT License (MIT)
 * Copyright (c) Gaaagaa. All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef __STD_QUEUE_INL__
#define __STD_QUEUE_INL__

#ifndef __STD_QUEUE_H__
#error "Please include std_queue.h before this file."
#endif // __STD_QUEUE_H__

#include "std_comm.inl"

////////////////////////////////////////////////////////////////////////////////
// xstd_queue_t 的相关数据类型定义

/** 块对象缓存是否与 所存储的元素数组缓存 分离 */
#define XQUE_CHUNK_SEPARATED 0

/** 块对象指针 */
typedef struct xque_chunk_t * xque_cptr_t;

/**
 * @struct xque_chunk_t
 * @brief  存储元素的内存块 结构体描述信息。
 */
typedef struct xque_chunk_t
{
    xque_cptr_t  xchk_next;    ///< 指向后继的块对象

#if XQUE_CHUNK_SEPARATED

    xstd_bptr_t  xchk_dptr;    ///< 块对象中所存储的元素数组缓存

#else // !XQUE_CHUNK_SEPARATED

#ifdef _MSC_VER
#pragma warning(disable:4200)
#endif // _MSC_VER
    xstd_byte_t  xchk_dptr[0]; ///< 块对象中所存储的元素数组缓存
#ifdef _MSC_VER
#pragma warning(default:4200)
#endif // _MSC_VER

#endif // XQUE_CHUNK_SEPARATED

} xque_chunk_t;

/**
 * @struct xstd_queue_t
 * @brief  FIFO 队列容器的结构体描述信息。
 */
typedef struct xstd_queue_t
{
    xstd_context_t  xstd_ectxt;  ///< 节点类型的上下文描述信息
    xque_size_t     xchk_size;   ///< 元素存储分块的 节点容量（取值为 2^N ）
    xque_size_t     xque_size;   ///< 当前存储的元素节点数量

    /**
     * 用于交换操作的备用缓存块 : 
     * 其用于暂存替换下来的内存块，若再次申请内存块时，
     * 优先使用该缓存块，减少系统调用方式的内存申请操作。
     */
    xque_cptr_t     xchk_rptr;

    /** 指向队列前端的块存储信息 */
    struct
    {
    xque_cptr_t     xchk_mptr;  ///< 内存块
    xque_size_t     xchk_npos;  ///< 当前存储节点的索引号
    } xque_front;

    /** 指向队列后端的块存储信息 */
    struct
    {
    xque_cptr_t     xchk_mptr;  ///< 内存块
    xque_size_t     xchk_npos;  ///< 当前存储节点的索引号
    } xque_back;
} xstd_queue_t;

////////////////////////////////////////////////////////////////////////////////
// xstd_queue_t 的相关操作宏函数

//====================================================================

#define XQUE_ECTXT(xque_this)   XSTD_ECTXT(xque_this)
#define XQUE_ETYPE(xque_this)   XSTD_ETYPE(xque_this)
#define XQUE_ESIZE(xque_this)   XSTD_ESIZE(xque_this)
#define XQUE_ALTOR(xque_this)   XSTD_ALTOR(xque_this)

#define XQUE_MALLOC(xque_this, xst_size)            \
            XSTD_MALLOC((xque_this), (xst_size))

#define XQUE_DEALLOC(xque_this, xmt_mptr)           \
            XSTD_DEALLOC((xque_this), (xmt_mptr))

#define XQUE_ALFROM(xque_this, xet_dptr, xet_sptr)  \
            XSTD_ALFROM((xque_this), (xet_dptr), (xet_sptr))

#define XQUE_ALMOVE(xque_this, xet_dptr, xet_sptr)  \
            XSTD_ALMOVE((xque_this), (xet_dptr), (xet_sptr))

#define XQUE_ALDEST(xque_this, xet_elem)            \
            XSTD_ALDEST((xque_this), (xet_elem))

#define XQUE_ISSAME_TYPE(xque_lthis, xque_rthis)    \
            XSTD_ISSAME_TYPE((xque_lthis), (xque_rthis))

#define XQUE_ECTXT_UPDATE(xque_this, xque_ctxt)     \
            XSTD_ECTXT_UPDATE((xque_this), (xque_ctxt))

//====================================================================

#if XQUE_CHUNK_SEPARATED
#define XQUE_SIZEOF_CHUNK(xque_this)  (sizeof(xque_chunk_t))
#else // !XQUE_CHUNK_SEPARATED
#define XQUE_SIZEOF_CHUNK(xque_this)  \
    (sizeof(xque_chunk_t) + (xque_this)->xchk_size * XQUE_ESIZE(xque_this))
#endif // XQUE_CHUNK_SEPARATED

#define XQUE_MAX_SIZE(xque_this) \
    ((xque_size_t)(((xque_size_t)~0) / XQUE_ESIZE(xque_this)))

#define XQUE_FRONT(xque_this)                                           \
    ((xque_elem_t)(                                                     \
        ((xstd_bptr_t)(xque_this)->xque_front.xchk_mptr->xchk_dptr) +   \
        (XQUE_ESIZE(xque_this) * (xque_this)->xque_front.xchk_npos)))

#define XQUE_BACK(xque_this)                                            \
    ((xque_elem_t)(                                                     \
        ((xstd_bptr_t)(xque_this)->xque_back.xchk_mptr->xchk_dptr) +    \
        (XQUE_ESIZE(xque_this) * (xque_this)->xque_back.xchk_npos)))

//====================================================================

////////////////////////////////////////////////////////////////////////////////

#endif // __STD_QUEUE_INL__
